package org.szy.core.common.uilts;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import org.noear.solon.core.handle.DownloadedFile;
import org.noear.solon.core.handle.UploadedFile;
import org.szy.core.common.exception.BaseException;
import org.szy.core.common.prop.FileProperties;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * 文件上传工具类
 *
 * @author wangbuhao
 * @date 2021/1/28
 **/
public class FileUploadUtils {


    /**
     * 根据文件路径上传
     *
     * @param baseDir 相对应用的基目录
     * @param file    上传的文件
     * @return 文件名称
     */
    public static String upload(String baseDir, UploadedFile file) {
        String accept = ReqUtil.getStr("accept");
        String[] allowed = MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION;
        if (StrUtil.isNotBlank(accept)) {
            allowed = StrUtil.splitToArray(accept, ",");
        }
        return upload(baseDir, file, allowed);
    }

    /**
     * 文件上传
     *
     * @param baseDir          相对应用的基目录
     * @param file             上传的文件
     * @param allowedExtension 允许上传文件类型
     * @return 返回上传成功的文件名
     */
    public static String upload(String baseDir, UploadedFile file, String[] allowedExtension) {
        int fileNameLength = file.getName().length();
        if (fileNameLength > FileProperties.fileMaxSize) {
            throw new BaseException("文件名长度超出系统最大限制。");
        }
        // 文件校验
        assertAllowed(file, allowedExtension);

        String fileName = generateFileAddress(file);

        File desc = getAbsoluteFile(baseDir, fileName);
        try {
            file.transferTo(desc);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BaseException(e.getMessage());
        }
        return getPathFileName(fileName);

    }

    /**
     * 文件大小/上传类型校验
     *
     * @param file             上传的文件
     * @param allowedExtension 允许上传文件类型
     */
    public static void assertAllowed(UploadedFile file, String[] allowedExtension) {
        long default_max_size = FileProperties.fileMaxSize;
        long size = file.getContentSize();

        if (default_max_size != -1 && size > default_max_size) {
            throw new BaseException("文件大小超出最大限制");
        }
        String extension = getExtension(file);
        String notAllowedExtension = FileProperties.notAllowedExtension;
        String[] notAllowed = StrUtil.splitToArray(notAllowedExtension, ",");
        if (allowedExtension != null && (!isAllowedExtension(extension, allowedExtension) || isAllowedExtension(extension, notAllowed))) {
            throw new BaseException("系统不允许该文件格式");
        }
    }


    /**
     * 判断MIME类型是否是允许的MIME类型
     *
     * @param extension        后缀名
     * @param allowedExtension 允许的后缀名集合
     * @return 是否允许
     */
    public static boolean isAllowedExtension(String extension, String[] allowedExtension) {
        for (String str : allowedExtension) {
            str = str.startsWith(".") ? str.substring(1) : str;
            if (str.equalsIgnoreCase(extension)) {
                return true;
            }
        }
        return false;
    }

    public static String getPathFileName(String fileName) {
        return File.separator + fileName;
    }

    /**
     * @param uploadDir 上传地址
     * @param fileName  文件名称
     * @return 文件
     */
    public static File getAbsoluteFile(String uploadDir, String fileName) {
        File desc = new File(uploadDir + File.separator + fileName);

        if (!desc.exists()) {
            if (!desc.getParentFile().exists()) {
                desc.getParentFile().mkdirs();
            }
        }
        return desc;
    }

    /**
     * 
     * 生成文件地址
     *
     * @param file 文件
     * @return yyyy-MM-dd/随机文件名
     */
    public static String generateFileAddress(UploadedFile file) {
        //String fileName = file.getOriginalFilename();
        String fileName = "";
        // 是否自定义目录
        String dir = ReqUtil.getStr("dir");
        if (StrUtil.isNotBlank(dir)) {
            fileName = dir;
        } else {
            fileName = "undefined";
        }
        if (!fileName.endsWith(File.separator)) fileName += File.separator;
        String extension = getExtension(file);
        fileName += DateUtil.today() + File.separator + IdUtil.fastUUID() + "." + extension;
        return fileName;
    }

    /**
     * 获取文件名的后缀
     *
     * @param file 表单文件
     * @return 后缀名
     */
    public static String getExtension(UploadedFile file) {
        String extension = file.getExtension();
        if (StrUtil.isEmpty(extension)) {
            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
        }
        if (StrUtil.isEmpty(extension)) {
            extension = FileUtil.getSuffix(file.getName());
        }
        return extension;
    }

    /**
     * 下载文件
     *
     * @param filePath 文件绝对位置
     * @param fileName 文件名称
     */
    public static DownloadedFile download(String filePath, String fileName) {
        try {
            InputStream is = new BufferedInputStream(new FileInputStream(filePath));
            return new DownloadedFile(FileUtil.getMimeType(filePath), is, fileName);
        } catch (Exception e) {
            byte[] bytes = ("文件下载失败，原因：" + e.getMessage()).getBytes(StandardCharsets.UTF_8);
            //使用 byte[] 实例化
            return new DownloadedFile("text/json", bytes, "失败.txt");
        }
    }
}
